<?php
namespace app\controller;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\RequestOptions;
use support\Request;
use OpenAI\Client;
// openai 的 key
// 全局代理后,在这里注册登录 https://platform.openai.com/signup
define('OPENAI_KEY', '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');
class ChatgptController
{
    // 初始化获取全部已回答
    public function all(Request $request){
        $messages = $request->session()->get('messages', []);
        return json([
            "code"=>0,
            "msg"=>"ok",
            "data"=>$messages
        ]);
    }

    // 单次查询
    public function query(Request $request)
    {
        $messages = $request->session()->get('messages', []);
        $messages[] = ['role' => 'user', 'content' => $request->input('message')];
        $current=[];
        try {
            // 旧版 <0.4 OpenAI 库 使用该代码
//            $response = \OpenAI::client(OPENAI_KEY)->chat()->create([
//                'model' => 'gpt-3.5-turbo',
//                'messages' => $messages
//            ]);
            // 新版 >=0.4 OpenAI 库使用该代码

            $response=\OpenAI::factory()
                ->withApiKey(OPENAI_KEY)
                ->withHttpClient(new \GuzzleHttp\Client([
                    /** 部署到香港服务器 不需要代理 */
                        "proxy"=>"http://http://156.236.71.182:80"
              ]))->make()->chat()->create([
                'model' => 'gpt-3.5-turbo',
                'messages' => $messages
            ]);

            $current = ['role' => 'assistant', 'content' => nl2br($response->choices[0]->message->content)];

            /** 另外一种方法 */
            /*$client = new \GuzzleHttp\Client(["proxy"=>"http://156.236.71.182:8001"]);
            $response = $client->request('post','https://api.openai.com/v1/chat/completions',[
                RequestOptions::HEADERS=>[
                    'Authorization'=>'Bearer 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',
                    'Content-Type'=>'application/json',
                ],
                RequestOptions::JSON => json_encode([ 'model' => 'gpt-3.5-turbo',  'messages' => $messages])
            ]);
            $current = ['role'=>'assistant','content'=>nl2br($response->getBody()->getContents()->choices[0]->message->content)];*/


        } catch (\Exception|GuzzleException $e) {
            var_dump("发生了异常");
            var_dump($e->getMessage());
            $current = ['role' => 'assistant', 'content' => $e->getMessage()];
        }
        $messages[]=$current;
        $request->session()->put('messages', $messages);
        return json([
            "code"=>0,
            "msg"=>"ok",
            "data"=>$current['content']
        ]);
    }
    // 清除
    public function clear(Request $request)
    {
        $request->session()->put('messages', []);
        return redirect("/");
    }
    public function index(Request $request)
    {
        $html=<<<'EOF'
        <!DOCTYPE html>
        <head>
            <meta charset="utf-8">
            <meta name="viewport" content="width=device-width, initial-scale=1">
            <title>ChatGPT</title>
            <link href="https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/tailwindcss/2.2.19/tailwind.min.css" type="text/css" rel="stylesheet" />
        </head>
        <body class="antialiased mx-auto" style="max-width:1000px">
            <div class="flex flex-col space-y-4 py-4 overflow-auto" id="body"></div>
            <div class="text-center text-red-400" id="loading"></div>
            <div class="py-4 flex flex-col space-x-1 justify-center items-center">
                <textarea required onkeypress="submit(this)" placeholder="输入后 ctrl+回车 或点击右侧 发送 按钮" name="message" class="border   p-2 flex-1 w-full" id="message"></textarea>
                <div class="flex justify-center items-center mt-2">
                    <input type="button" onclick="submit(this,'click')" class="cursor-pointer bg-green-500 text-white p-2  mx-1" value="发送请求" />
                    <a class="bg-gray-200 text-white p-2  mx-1" href="./clear" title="出现错误时,可尝试清除提问记录">清除记录</a>
                </div>
            </div>
            <script>
            // 名称
            window.chatgptConfig = {
                "assistant": "ChatGPT",
                "user": "我"
            };
            window.onload = function() {
                fetch("./all", {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json',
                            'X-Requested-With': 'XMLHttpRequest'
                        },
                        body: ''
                    })
                    .then(response => response.json()) 
                    .then(json => {
                        if (json.data) {
                            json.data.forEach(it => {
                                append(it['content'], window.chatgptConfig[it.role]);
                            });
                        }
                    })
                    .catch(error => {
                        console.error(error);
                    });
            };
            function submit(el, type) {
                if (type === 'click' || (event.ctrlKey && event.keyCode === 10)) {
                    if (el.getAttribute('disabled')) {
                        alert("正在等待上次提问的回复,请稍等");
                        return;
                    }
                    var msg = document.getElementById('message').value.trim();
                    if (!msg) {
                        alert("必须输入问题");
                        return;
                    }
                    el.setAttribute('disabled', 'disabled');
                    append(msg, window.chatgptConfig['user']);
                    document.getElementById('loading').innerHTML = "努力思考中,稍等哦...";
                    document.documentElement.scrollTop+=50;
                    fetch("./query", {
                            method: 'POST',
                            headers: {
                                'Content-Type': 'application/json',
                                'X-Requested-With': 'XMLHttpRequest'
                            },
                            body: JSON.stringify({ message: msg})
                        })
                        .then(response => response.json())
                        .then(json => {
                            append(json.data, window.chatgptConfig["assistant"]);
                            document.getElementById('loading').innerHTML = '';
                            document.getElementById('message').value = '';
                            el.removeAttribute('disabled', 'disabled');
                        })
                        .catch(error => {
                            console.error(error);
                            el.removeAttribute('disabled', 'disabled');
                        });
                }
            }
            function append(msg, name) {
                var html = `
                    <div class="ml-4">
                        <div class="text-lg">
                            <a href="#" class="font-medium ${name==window.chatgptConfig['assistant']?'text-green-400':'text-gray-900'}">${name}:</a>
                        </div>
                        <div class="mt-1">
                            <p class="text-gray-800">
                                ${msg}
                            </p>
                        </div>
                    </div>
                `;
                const newDiv = document.createElement("div");
                newDiv.className=`overflow-auto flex p-4 ${name==window.chatgptConfig['assistant']?'bg-gray-100 border flex-reverse':""}`;
                newDiv.innerHTML = html;
                const bodyDiv = document.getElementById("body");
                bodyDiv.appendChild(newDiv);
            }
            </script>
        </body>
        </html>
EOF;
        return $html;
    }
}